﻿/**
 * 组件 
 */
package CutLoad.components
{
	import CutLoad.Base;
	import CutLoad.cookies.CLoadImg;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextFormat;

	/**
	 * 按钮 
	 * <p>实现的原理就是四个状态的元件，需要哪一个显示哪一个。</p>
	 * <ol>该按钮的特色：
	 * <li>可以自己设置状态 </li>
	 * <li>可以设置成按钮根据文字长或高自动适应，或者设置固定长高,加载外部图片做为按钮状态。</li>
	 * </ol>
	 * @author smallerbird mail:smallerbird@gmail.com  site:www.mkigm.com QQ群:49983196
	 * 
	 */	
	public class CButton extends Base
	{
		//
		private var arrMc:Array=new Array();
		//
		private var txtLable:CTextField=null
		private var strLableText:String="";
		//按钮当前状态
		private var numCurrentState:Number=0
		//文本框的两种状态
		private var txtFormat1:TextFormat=null;
		private var txtFormat2:TextFormat=null;
		private var txtOffsetX:Number;
		private var txtOffsetY:Number;
		//按钮是否不起作用
		private var isOff:Boolean
		//
		private var isDown:Boolean
		//是否自动适应宽
		private var isAutoW:Boolean
		//是否自动适应宽
		private var isAutoH:Boolean
		//是否水平居中
		private var isXCenter:Boolean;
		//是否垂直居中
		private var isYCenter:Boolean;
		//
		/**
		 * 获得一个简单的按钮，只提供划按钮的名称 
		 * @param label
		 * @param funClick 默认空,按钮点击回调方法   格式：function(自已:CButton)
		 * @return 
		 * 
		 */			
		public static function getSimpleBtn(label:String,funClick:Function=null):CButton{
			var btn:CButton=new CButton();
			btn.init(label);
			if(funClick!=null){
				btn.setOtherInfo({getgetSimpleBtn_for_click_fun:funClick});
				btn.addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{
					var btn:CButton=e.target as CButton;
					var obj:Object=btn.getOtherInfo();
					obj.getgetSimpleBtn_for_click_fun(btn);
				});
			}
			return btn;
		}
		/**
		 * 获得一批简单的按钮，只提供划按钮的名称
		 * @param arrLabel [按钮标签1,按钮标签2,按钮标签3,按钮标签4....]
		 * @param funClick 点击这些按钮,调用的方法.格式:function(id:索引号从0开始)       注:实现这个方法,是使用了Base.setOtherInfo()的方法,来附架额外属性.这些属性分别为:
		   getSomeSimpleBtn_for_click_id:保存引号,
		   getSomeSimpleBtn_for_click_fun:funClick 调用的方法.
		 * @return 
		 * 
		 */		
		public static function getSomeSimpleBtn(arrLabel:Array,funClick:Function=null):Array{
			var arr:Array=new Array();
			for(var i:Number=0;i<arrLabel.length;i++){
				var btnTem:CButton=getSimpleBtn(arrLabel[i]);
				if(funClick!=null){
					btnTem.setOtherInfo({
						getSomeSimpleBtn_for_click_id:i,
						getSomeSimpleBtn_for_click_fun:funClick
					});
					if(!btnTem.hasEventListener(MouseEvent.CLICK)){
						btnTem.addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{
							var btn:CButton=e.target as CButton;
							var obj:Object=btn.getOtherInfo();
							obj.getSomeSimpleBtn_for_click_fun(obj.getSomeSimpleBtn_for_click_id);
						});
					}
				}
				arr.push(btnTem);
			}
			return arr
		}
		//
		//
		/**
		 * 按钮组件
		 * @param strLableText 按钮上的文字,可以为空;如果为空：后面两个参数:isAutoW和isAutoH 自动设为false
		 * @param isAutoW 根据文本内容适应宽,如果设为:false ,则可以使用setWH(..),设置它的宽度
		 * @param isAutoH 根据文本内容适应高,如果设为:false ,则可以使用setWH(..),设置它的高度
		 * @param isXCenter 是否水平居中
		 * @param isYCenter 是否垂直居中
		 * @param otherInfo 其它文本信息，如果想让按钮包括一些信息的话，这样省去自定义事件。
		 * @return 
		 * 
		 */		
		public function init(strLableText:String="",isAutoW:Boolean=true,isAutoH:Boolean=true,isXCenter:Boolean=true,isYCenter:Boolean=true,otherInfo:Object=null):CButton{
			if(otherInfo!=null){
				this.appendOtherInfo(otherInfo);
			}
			this.isYCenter=isYCenter
			this.isXCenter=isXCenter;
			//
			if(strLableText!=""){
				this.isAutoH=isAutoH;
				this.isAutoW=isAutoW;
			}else{
				this.isAutoH=false;
				this.isAutoW=false;
			}
			//
			this.mouseChildren=false
			//如果之前调用过setSkin,这里就不用再调用了。
			if(arrMc.length==0){
				setSkin(Skin.getInstance().getSkin(0),strLableText)
			}
			iniState()
			return this
		}	
		/**
		 * 设置按钮的皮肤的四种状态:显示，鼠标放上去，按下,不起作用时
		 * @param arrClassName 按钮四种状态需要的显示对象类的数组列表格式：[up,over,down,hit]，也可以设置两种，如果设置两种函数会自动设成：[up,over,up,over]
		 * @param btnLable 如果为空，以后都不能加文字显示了。
		 * @return 
		 * 
		 */		
		public function setSkin(arrClassName:Array,btnLable:String=""):CButton{
			var _mcup:Sprite=Base.getStrClassObject(arrClassName[0]) as Sprite
			var _mcover:Sprite=Base.getStrClassObject(arrClassName[1]) as Sprite
			var _mcDown:Sprite
			if(arrClassName.length==2){
				_mcDown=Base.getStrClassObject(arrClassName[0]) as Sprite
			}else{
				_mcDown=Base.getStrClassObject(arrClassName[2]) as Sprite
			}
			
			var _mcDisabled:Sprite
			if(arrClassName.length==2){
				_mcDisabled=Base.getStrClassObject(arrClassName[1]) as Sprite
			}else{
				_mcDisabled=Base.getStrClassObject(arrClassName[3]) as Sprite
			}
			setDisplayObjState([_mcup,_mcover,_mcDown,_mcDisabled],btnLable);
			return this
		}
		/**
		 * 用flash的显示对象做为按钮的四个状态
		 * @param arrDisplayObj 状态格式:[up,over,down,hit]，也可以设置两种，如果设置两种函数会自动设成：[up,over,up,over]
		 * @param btnLable 按钮标签
		 * 
		 */		
		public function setDisplayObjState(arrDisplayObj:Array,btnLable:String=""):CButton{
			if(arrDisplayObj.length==2){
				arrDisplayObj.push(arrDisplayObj[0]);
				arrDisplayObj.push(arrDisplayObj[1]);
			}
			this.addChild(arrDisplayObj[0]);
			this.addChild(arrDisplayObj[1]);
			this.addChild(arrDisplayObj[2]);
			this.addChild(arrDisplayObj[3]);
			//
			if(arrMc.length!=0){
				this.removeChild(arrMc[0]);
				this.removeChild(arrMc[1]);
				this.removeChild(arrMc[2]);
				this.removeChild(arrMc[3]);
			}
			arrMc=new Array();
			
			arrMc.push(arrDisplayObj[0]);
			arrMc.push(arrDisplayObj[1]);
			arrMc.push(arrDisplayObj[2]);
			arrMc.push(arrDisplayObj[3]);
			//
			if(txtLable!=null) this.removeChild(txtLable);
			//钮添加文字标标
			if(btnLable!=""){
				this.strLableText=btnLable;
				txtLable=new CTextField();
				var arrButnConTem:Array=Skin.getInstance().getSkin();
				if(txtFormat1==null) txtFormat1=CTextField.getTextFormat(0,arrButnConTem[4],arrButnConTem[5]);
				if(txtFormat2==null) txtFormat2=CTextField.getTextFormat(0,arrButnConTem[6],arrButnConTem[7])
				txtOffsetX=arrButnConTem[8];
				txtOffsetY=arrButnConTem[9];
				txtLable.init("",txtFormat1);
				//txtLable.getTextField().border=true;
				setText(strLableText);
				updateWHForTxt_main(this.isAutoW,this.isAutoH)
				this.addChild(txtLable);
			}
			//			
			iniState()
			return this;
		}
		/**
		 * 设置按钮标签的两种状态:没有按时，滑过时的状态,注：使用此方法应在调用init前使用，才能立即生效 
		 * @param txtFormat1  没有按时
		 * @param txtFormat2 滑过时的状态
		 * 
		 */		
		public function set2TextFormat(txtFormat1:TextFormat,txtFormat2:TextFormat):void{
			this.txtFormat1=txtFormat1;
			this.txtFormat2=txtFormat2;
		}
		//没有文本抛出异常
		private function throwErronNoTxt():void{
			if(txtLable==null) throw new Error("文字不存在，请确保你初始方法中是否有设置：init(...)");
		}
		private function updateWForTxt():void{
			throwErronNoTxt()
			updateWHForTxt_main(true,false)
		}
		/**
		 * 根据文本的内容更新按钮的高度
		 * 
		 */	
		public function updateHForTxt():void{
			throwErronNoTxt()
			updateWHForTxt_main(false,true)
		}
		/**
		 * 根据文本的内容更新按钮的宽度和高度
		 * 
		 */	
		public function updateWHForTxt():void{
			throwErronNoTxt()
			updateWHForTxt_main(true,true)
		}
		//
		private function updateWHForTxt_main(isW:Boolean,isH:Boolean):void{
			if(!isW&&!isH) return;
			var arrButnConTem:Array=Skin.getInstance().getSkin();
			var ww:Number=txtLable.getShowWidth()+arrButnConTem[10]*2;
			var hh:Number=txtLable.getShowHeight()+arrButnConTem[11]*2;
			for(var i:Number=0;i<arrMc.length;i++){
				if(isW) arrMc[i].width=ww;
				if(isH) arrMc[i].height=hh;
			}
		}
		private function iniState():void{
			setOn()
			isDown=false
			this.addEventListener(MouseEvent.MOUSE_DOWN,funevent);
			this.addEventListener(MouseEvent.MOUSE_UP,funevent);
			this.addEventListener(MouseEvent.MOUSE_OVER,funevent);
			this.addEventListener(MouseEvent.MOUSE_OUT,funevent);
		}
		/**
		 * 设置按钮的状态 
		 * @param s 可以设置以下状态：up,over,down,disabled分别代表的值：0,1,2,3
		 * 
		 */		
		public function setState(s:uint=0):void{
			//文本的状态
			if(strLableText!=""){
				if(s==1){
					reSetTxtState(false)
				}else{
					reSetTxtState(true)
				}				
			}			
			//
			if(s!=1&&s!=2&&s!=3&&s!=0){
				throw new Error("设置按钮状态的值错误，只能0,1,2,3");
			}
			this.numCurrentState=s
			for(var i:Number=0;i<arrMc.length;i++){
				arrMc[i].visible=false
			}
			arrMc[s].visible=true
		}
		/**
		 * 设置按钮是否起作用 
		 * @param isOk true：起作用，false:不起作用
		 * 
		 */		
		public function set enable(isOk:Boolean):void{
			if(isOk){
				setOn()
			}else{
				setOff()
			}
		}
		/**
		 * 设置按钮不起作用 
		 * 
		 */		
		private function setOff():void{
			isOff=true
			setState(3)
			this.buttonMode=false
			this.mouseEnabled=false;
		}
		/**
		 * 设置按钮起作用 
		 * 
		 */		
		private function setOn():void{
			this.buttonMode=true
			this.mouseEnabled=true;
			isOff=false;
			setState(0)
		}
		/**
		 * 获得按钮是否可用 
		 * @return 
		 * 
		 */		
		public function getIsOff():Boolean{
			return isOff;
		}
		private function funevent(e:MouseEvent):void{
			if(isOff) return;
			switch(e.type){
				case MouseEvent.MOUSE_DOWN:
					setState(2)
					isDown=true
					break;
				case MouseEvent.MOUSE_UP:
					setState(1)	
					isDown=false
					break;
				case MouseEvent.MOUSE_OVER:
					if(isDown) return;
					setState(1)					
					break;
				case MouseEvent.MOUSE_OUT:
					setState(0)
					isDown=false
					break;
			}
		}
		//替换状态加载图片-----------------------start---------------------------------
		/**
		 * 更换按钮状态为加载图片，当图片加载完成时，来替换 
		 * @param arrUrl 图片地址列表数组，可以设置为两个图片或四个图片
		 * 
		 */		
		public function setLoadImgState(arrUrl:Array,w:Number,h:Number):void{
			if(arrUrl.length!=2&&arrUrl.length!=4){
				throw new Error("图片的地址可以是两个或者四个");
			}
			if(arrUrl.length==2){
				creatOneLoadimg(arrUrl[0],0,w,h)
				creatOneLoadimg(arrUrl[1],1,w,h)
				creatOneLoadimg(arrUrl[0],2,w,h)
				creatOneLoadimg(arrUrl[0],3,w,h)
			}else{
				creatOneLoadimg(arrUrl[0],0,w,h)
				creatOneLoadimg(arrUrl[1],1,w,h)
				creatOneLoadimg(arrUrl[2],2,w,h)
				creatOneLoadimg(arrUrl[3],3,w,h)
			}		
			if(this.txtLable!=null){
				this.swapChildren(this.arrMc[3],this.txtLable);
			}
			//
			this.isAutoH=this.isAutoW=false;
			this.setWH(w,h);
			//
			updateTxtXY()
		}
		//替换一个状态
		private function creatOneLoadimg(url:String,index:Number,w:Number,h:Number):CLoadImg{
			this.removeChild(this.arrMc[index]);
			this.arrMc[index]=new CLoadImg(url,w,h)
			this.addChild(this.arrMc[index]);	
			return this.arrMc[index]
		}
		//------------------------------------方本框-----------------------------------
		private function setText(str:String=""):void{
			if(str=="") this.isAutoW=this.isAutoH=false;
			strLableText=str;
			txtLable.text=str;
			//根据文本内容适应宽
			if(this.isAutoW){
				updateWForTxt()
			}
			//根据文本内容适应高
			if(this.isAutoH){
				updateHForTxt()
			}
			updateTxtXY()
		}
		/**
		 * 刷新 
		 * 
		 */		
		public function refresh():void{
			setText(strLableText)
		}
		/**
		 * 按钮的宽度，自动适应文字的宽度 
		 * @param isOk
		 * 
		 */		
		public function set AutoResizeWidth(isOk:Boolean):void{
			isAutoW=isOk
			refresh();
		}
		/**
		 * 按钮的高度，自动适应文字的高度
		 * @param isOk
		 * 
		 */		
		public function set AutoResizeHeight(isOk:Boolean):void{
			isAutoH=isOk
			refresh();
		}
		//
		//获是按钮的标签内容
		private function getText():String{
			return txtLable.text;
		}
		/**
		 * 设置按钮上的文字
		 * @param str
		 * 
		 */
		public function set label(str:String):void{
			this.setText(str);
		}
		/**
		 * 获是按钮的标签内容
		 * @return 
		 * 
		 */	
		public function get label():String{
			return getText();
		}
		public function setFontSize(size:Number=12):void{
			if(strLableText==""){
				throw new Error("警告:此按钮在初始化的时候没有设置有文本，所以此方法无效!");
			}
			/*var arrButnConTem:Array=Skin.getInstance().getSkin();
			txtFormat1=CTextField.getTextFormat(0,arrButnConTem[4],size);
			txtFormat2=CTextField.getTextFormat(0,arrButnConTem[6],size);*/
			//
			reSetTxtState();
			
		}
		//更新方本框的位置
		private function updateTxtXY():void{
			var xx:Number=this.getShowWidth()-txtLable.getShowWidth();
			if(xx<=0) return;
			var yy:Number=this.getShowHeight()-txtLable.getShowHeight();
			if(yy<=0) return;
			if(isXCenter){
				txtLable.x=Math.abs((xx)/2)+txtOffsetX;
			}else{
				txtLable.x=txtOffsetX;
			}
			if(isYCenter){
				txtLable.y=Math.abs((yy)/2)+txtOffsetY;	
			}else{
				txtLable.y=txtOffsetY;
			}
		}
		/**
		 * 
		 * @param isXCenter 水平居中
		 * @param isYCenter 垂直居中
		 * 
		 */		
		public function setIsXYCenter(isXCenter:Boolean,isYCenter:Boolean):void{
			this.isYCenter=isYCenter;
			this.isXCenter=isXCenter;	
			refresh();
			
		}
		//更新方框的状态
		private function reSetTxtState(isOne:Boolean=true):void{
			if(isOne){
				txtLable.getTextField().defaultTextFormat=this.txtFormat1
			}else{
				txtLable.getTextField().defaultTextFormat=this.txtFormat2
			}
			setText(strLableText);
		}
		//覆盖
		override public function setWH(w:Number=0, h:Number=0):void{		
			if(w==0) w=this.getShowWidth();
			if(h==0) h=this.getShowHeight();
			for(var i:Number=0;i<this.arrMc.length;i++){
				//如果是加载来的图片
				if(this.arrMc[i] is CLoadImg){
					this.arrMc[i].setWH(w,h);
				}else{
					//系统皮肤
					if(!this.isAutoW) this.arrMc[i].width=w;
					if(!this.isAutoH) this.arrMc[i].height=h;
				}
				
			}
			updateWHForTxt_main(this.isAutoW,this.isAutoH);
			updateTxtXY()
		}
		override public function getShowWidth():Number
		{
			if(arrMc.length==0) return super.getShowWidth()
			if(arrMc[this.numCurrentState] is Base){
				return arrMc[0].getShowWidth()
			}
			return arrMc[numCurrentState].width;
		}
		
		override public function getShowHeight():Number
		{
			if(arrMc.length==0) return super.getShowHeight()
			if(arrMc[this.numCurrentState] is Base){
				return arrMc[0].getShowHeight()
			}
			return arrMc[numCurrentState].height;
		}
	}
}